<?php
namespace App\Api\Controllers\Hltx;


use App\Common\Log;

class BaseController extends \App\Api\Controllers\BaseController
{
    public $isvId = "V0009155";
    public $sign_type = "RSA";
    public $md5_key = '';
    public $version = '1.0.0';
    public $charset = 'UTF-8';
    public $ali_pid;
    public $wx_channelid;
    public $subscribe_appid;
    public $wx_appid;
    public $wx_secret;
    public $merchant_notify_url;
    public $public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLLBufs1HdWcMvantbQNwsqILaQ1vukul5G00hqKxc+tnMTgRc9vnRLqdNIBX8Rmilp+8v/qfhnWhe+/oIQYwEtzE8BhuJx4BiPNBrPVabXAPJZzaGZO6v6Hb5Fp0XTwlDlAiK7zVDGFeEKy6e3/uOboJtC9r6NzMcVjF8K4lOMwIDAQAB";
    public $private_key = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANfUwLyA4PbUK8erxOG2CiS7UtX/+SSDYbCSESsHBs3Cl47TrEnXDbDu3JluyF+TE9AOCbMxVfEfFbQ0NcTk6ENGOZiZFdij7TVLXwDkzcTsB8kL8VrdcSFtLm3sJ//6qM1grolqr8/qB9ojDQvGSlCWIslN7r2kOhOAnlEmyvnfAgMBAAECgYAQFL8DjIq2eVqFtwulUZ3x3K8wWLEkglF+CXQUA6MDI7ONJcJZghd4DmQLXpC5Zkj8oH8ihdOEcq94TMeQ0wlnDrVKTPBR7Oyzbnz+0OE2s0wNn0tppt5sQFpXed3ja4HvCe84ojMRKZhUTW6kntMBBFLeZMGyNpMemsYZzvS94QJBAPn8wOrh+Bug5jy/+GsJwn36HYzp6buQHH8tO54M0x8D38AY+hzXiol2LXQcbDZ55eOAjbQcjrn8xkmdkW0R1jECQQDdBbBmm4guMi59e0MYaFZJNdVDGnnEm5mSR3UV/Yn/57D59VBRRKut+kV3r1lj5nHCGwn46yPWuCDQoPyx4f0PAkBoO8k8pqfK7VXSssCj8NfVqzozDT1V5YrcREH9bp+A6R6cfE2dRQoQsuPU7Bz6wezm5S0wkk+4oPsUqsx+S9ehAkEAi1Ze0xESVS1Fqc3fiq+cViMeA2PZiF0f/9wUsHxaV35VT/+bVuCX6uJwkPd2v0g0R06MhuSWf3MtHNmg9POneQJAO5le16U+5TS4h2FlVHJN73+klHITmC8JTw1X6pOFEcDt1C1WD90oiRkJaXN/EAwKDARJsb364YKi/dvD4ztaLQ==";

    public $hltx_host_url_pro = "https://api.hulupos.com/isv/";
    public $hltx_host_url_test = "https://api.hulupos.com/isv/";

    public $upload_img_url = "gateway/isv/photo/upload";
    public $merchant_admission_url = "gateway/isv/merchant/admission";
    public $merchant_query_url = "gateway/isv/merchant/baseInfoQuery";
    public $merchant_edit_baseinfo_url = "gateway/isv/merchant/baseInfoUpdate";
    public $merchant_edit_payinfo_url = "gateway/isv/merchant/payInfoUpdate";
    public $merchant_admission_result_query_url = "gateway/isv/merchant/enterResultQuery";
    public $prepay_url = "gateway/isv/trade/prePay";
    public $scanpay_url = "gateway/isv/trade/pay";
    public $cancel_order_url = "gateway/isv/trade/cancelOrder";
    public $close_order_url = "gateway/isv/trade/closeOrder";
    public $refund_order_url = "gateway/isv/trade/refundPay";
    public $query_order_url = "gateway/isv/trade/queryOrder";
    public $merchant_wxset_url = "gateway/isv/wx/developConfig";
    public $get_openid = "gateway/isv/trade/queryUserId";

    public $debug = false;
    public  $img_arr = [
        'head_sfz_img_a' => '0001', //身份证正面
        'head_sfz_img_b' => '0002', //身份证反面
        'store_license_img' => '0003', //营业执照
        'store_industrylicense_img' => '0005', //开户许可证
        'store_logo_img' => '0006', //门头照
        'store_img_a' => '0008', //收银台照片
        'store_img_b' => '0009', //门店内景照片
        'store_img_c' => '0012', //门店外景照
        'merchant_trade_agreement' => '0013', //商户收单协议照片
        'bank_img_a' => '0015', //银行卡正面照
        'bank_img_b' => '0016', //银行卡背面照
        'bank_sfz_img_a' => '0017', //被授权人身份证正面
        'bank_sfz_img_b' => '0018', //被授权人身份证反面
        'store_auth_bank_img' => '0014', //结算授权书
    ];
    public  $img_desc_arr = [
        'head_sfz_img_a' => '身份证正面',
        'head_sfz_img_b' => '身份证反面',
        'store_license_img' => '营业执照',
        'store_industrylicense_img' => '开户许可证',
        'store_logo_img' => '门头照',
        'store_img_a' => '收银台照片',
        'store_img_b' => '门店内景照片',
        'store_img_c' => '门店外景照',
        'merchant_trade_agreement' => '商户收单协议照片',
        'bank_img_a' => '银行卡正面照',
        'bank_img_b' => '银行卡背面照',
        'bank_sfz_img_a' => '被授权人身份证正面',
        'bank_sfz_img_b' => '被授权人身份证反面',
        'store_auth_bank_img' => '结算授权书',
    ];
    public $merchant_type = [
        1 => 'MERCHANT_02', //个体工商户
        2 => 'MERCHANT_03', //企业
        3 => 'MERCHANT_01', //自然人
    ];
    public $result_arr = [
        '00' => '入驻成功（审核通过并且所有通道报备成功）' ,
        '01' => '入驻失败（审核驳回或全部报备失败）' ,
        '02' => '已提交基本信息（审核通过待报备）' ,
        '03' => '报备中（审核通过报备部分成功）' ,
        '04' => '入驻审核中（审核工单审核中）' ,
        '05' => '工单待提交' ,
    ];


    public function __construct()
    {

    }


    public function getReqMsgId()
    {
        return date('YmdHis') . (str_pad(rand(0, 10000), 5, STR_PAD_LEFT));
    }


    public function upload_img($path,$pic_name)
    {
        $reqMsgId = $this->getReqMsgId();
        $picData = $this->image2base64($path);
        $params = [
            'picName' => $this->img_arr[$pic_name].'.jpg',
            'picture' => $picData,
            'picType' => $this->img_arr[$pic_name]
        ];
        $result = $this->public_request($reqMsgId,$params,$this->upload_img_url);

        return $result;
    }


    public function image2base64($image_path)
    {
        if($this->check_file_exist($image_path)){
            $image_info = getimagesize($image_path);
            $base64_image_content = "data:{$image_info['mime']};base64," . base64_encode(file_get_contents($image_path));

            return $base64_image_content;
        }

        return '';
    }


    public function check_file_exist($path){
        if (strtolower(substr($path, 0, 4)) == 'http') {
            $header = get_headers($path, true);

            return isset($header[0]) && (strpos($header[0],'200') || strpos($header[0],'304'));
        } else {
            //本地文件
            return file_exists($path);
        }
    }


    public function public_request($reqMsgId, $business_parameters = [], $method = null)
    {
        $header = array(
            "content-Type" => "application/json"
        );
        $common_params = [
            'isvId' => $this->isvId,
            'reqMsgId' => $reqMsgId,
            'version' => $this->version,
            'charset' => $this->charset,
            'signType' => $this->sign_type,
            'timestamp' => date('YmdHis').'',
        ];
        $post_data = $common_params + $business_parameters;

        //生成签名
        $post_data['signature'] = $this->makeSign($post_data);
        Log::write($post_data);

        $this->debug ? $url = $this->hltx_host_url_test : $url = $this->hltx_host_url_pro;
        $url = $url . $method;
        $result = $this->post_func($url, $post_data, $header);
        if($result&&$result['status'] == 1){
            $response_content = json_decode($result['data'], true);
            Log::write($response_content);

            if($response_content['code'] === '0000' && isset($response_content['signature'])){
                if ($this->signVerify($response_content)) {
                    return [
                        'status' =>1,
                        'data' => $response_content
                    ];
                } else {
                    $result = [
                        'status' => 0,
                        'message' => '签名错误'
                    ];
                }
            }else{
                $code = isset($response_content['errorCode']) ? $response_content['errorCode'] : $response_content['code'];
                $message = isset($response_content['message']) ? $response_content['message'] : '接口错误';
                $result = [
                    'status' => 0,
                    'message' => $message.$code
                ];
            }
        }

        return $result;
    }


    //发起POST请求
    public function post_func($url, $post_data = '', $header_data = [], $timeout = 20, $type = '')
    {
        $ch = curl_init();
        curl_setopt ($ch, CURLOPT_URL, $url);

        if($type == ''){
            curl_setopt ($ch, CURLOPT_POST, 1);
        }else{
            curl_setopt ($ch, CURLOPT_POST, false);
        }

        if($post_data != ''){
            Log::write(json_encode($post_data,JSON_UNESCAPED_UNICODE));
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data,JSON_UNESCAPED_UNICODE));
        }

        $o = array();
        foreach ( $header_data as $k => $v )
        {
            $o[] = "$k: $v";
        }

        $header_data = $o;

        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header_data);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //本地忽略校验证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $file_contents = curl_exec($ch);
        $errmsg = '';

        if(curl_errno($ch)){
            $errmsg = '请求错误:'.curl_error($ch);
        }

        curl_close($ch);

        if ($errmsg != '') {
            return [
                'status'=>0,
                'message'=>$errmsg
            ];
        }

        return [
            'status' => '1',
            'data' => $file_contents
        ];
    }


    /**
     * 生成签名
     * @param $data
     * @return string
     */
    public function makeSign($data)
    {
        switch ($sign_type = $this->sign_type) {
            case 'RSA':
                $sign = $this->rsaSign($data);
                break;
            default:
                $sign = $this->md5Sign($data);
        }

        return $sign;
    }


    //参数拼接
    public function getSignContent($params)
    {
        ksort($params);

        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
                // 转换成目标字符集
                $v = $this->characet($v, $this->charset);

                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }

        unset ($k, $v);
        return $stringToBeSigned;
    }


    /**
     * 转换字符集编码
     * @param $data
     * @param $targetCharset
     * @return string
     */
    function characet($data, $targetCharset)
    {


        if (!empty($data)) {
            $fileType = $this->charset;
            if (strcasecmp($fileType, $targetCharset) != 0) {

                $data = mb_convert_encoding($data, $targetCharset);
                //				$data = iconv($fileType, $targetCharset.'//IGNORE', $data);
            }
        }


        return $data;
    }


    /**
     * 校验$value是否非空
     *  if not set ,return true;
     *    if is null , return true;
     **/
    protected function checkEmpty($value)
    {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;

        return false;
    }


    public function signVerify($data)
    {
        switch ($sign_type = $this->sign_type) {
            case 'RSA':
                $check_status = $this->rsaVerify($data, $data['signature']);
                break;
            default:
                $client_sign = $this->md5Sign($data);
                $client_sign == $data['sign'] ? $check_status = true : $check_status = false;
        }
        return $check_status;
    }


    public function md5Sign($data)
    {
        $sign_str = $this->getSignContent($data);
        $str = $sign_str . '&key=' . $this->md5_key;

        $sign = strtoupper(md5($str));
        return $sign;
    }


    /**
     * 加签
     * @param $content
     * @return string
     */
    public function rsaSign($content)
    {
        $content = $this->arrayToString($content);
        $content = hash('sha256', $content);
        Log::write($content);

        // 计算出签名值
        $pri_key = $this->private_key;
        $pri_key_f = $this->formatPriKey($pri_key);
        $privKeyId = openssl_pkey_get_private($pri_key_f);
        $signature = '';
        openssl_sign($content, $signature, $privKeyId, OPENSSL_ALGO_SHA256);
        openssl_free_key($privKeyId);

        //base64编码
        return base64_encode($signature);
    }


    /**
     * 数组转字符串
     **/
    private function arrayToString($params)
    {
        if (isset($params['signature']) || isset($params['file'])) {
            unset($params['signature']);
            unset($params['file']);
        }
        ksort($params);
        $sign_str = '';
        foreach ($params as $key => $val) {
            if ($val != "") {
                if (is_array($val)) {
                    ksort($val);
                    $val = str_replace("\\/", "/", json_encode($val, JSON_UNESCAPED_UNICODE));
                    $sign_str .= sprintf("%s=%s&", $key, $val);
                } else {
                    $sign_str .= sprintf("%s=%s&", $key, $val);
                }
            }
        }

        return substr($sign_str, 0, strlen($sign_str) - 1);
    }


    /**
     * 验签
     * @param $content
     * @param $sign
     * @return bool
     */
    public function rsaVerify($content, $sign)
    {
        $content = $this->arrayToString($content);
        Log::write($content);

        $content = hash('sha256', $content);
        $pub_key = $this->public_key;
        $pub_key_f = $this->formatPubKey($pub_key);
        $publicKeyId = openssl_pkey_get_public($pub_key_f);
        $sign = base64_decode($sign);
        $result = openssl_verify($content, $sign, $publicKeyId, OPENSSL_ALGO_SHA256);
        Log::write($result);

        openssl_free_key($publicKeyId);

        return $result === 1 ? true : false;
    }


    /**
     * 格式化rsa私钥
     * @param $priKey
     * @return string
     */
    public function formatPriKey($priKey)
    {
        $fKey = "-----BEGIN PRIVATE KEY-----\n";
        $len = strlen($priKey);
        for ($i = 0; $i < $len;) {
            $fKey = $fKey . substr($priKey, $i, 64) . "\n";
            $i += 64;
        }
        $fKey .= "-----END PRIVATE KEY-----";

        return $fKey;
    }


    /**
     * 格式化rsa公钥
     * @param $pubKey
     * @return string
     */
    public function formatPubKey($pubKey)
    {
        $fKey = "-----BEGIN PUBLIC KEY-----\n";
        $len = strlen($pubKey);
        for ($i = 0; $i < $len;) {
            $fKey = $fKey . substr($pubKey, $i, 64) . "\n";
            $i += 64;
        }
        $fKey .= "-----END PUBLIC KEY-----";

        return $fKey;
    }


}
